<script setup lang="ts">
import sparkMD5 from 'spark-md5'
import { ref } from 'vue'
import axios from 'axios'
const CHUNK_SIZE = 1024 * 1024 // 1024*1024=1M 需要切片的大小
const fileHash = ref<string>('')
const fileName = ref<string>('')
// 2.文件分片
const createFileChunks = (file: File) => {
     const fileChunkList = []
     let cur = 0
     while (cur < file.size) {
          fileChunkList.push({
               file: file.slice(cur, cur + CHUNK_SIZE)
          })
          cur += CHUNK_SIZE // CHUNK_SIZE为分片的大小
     }
     return fileChunkList
}
/**
 *  3.hash 计算 使用 spark-md5 生成 hash值用于 区分文件
 * 计算文件的hash值，计算的时候并不是根据所用的切片的内容去计算的，那样会很耗时间，我们采取下面的策略去计算：
 * 1. 第一个和最后一个切片的内容全部参与计算
 * 2. 中间剩余的切片我们分别在前面、后面和中间取2个字节参与计算
 * 这样做会节省计算hash的时间
 */
const calculateHash = async (fileChunks: Array<{ file: Blob }>) => {
     return new Promise((resolve) => {
          const spark = new sparkMD5.ArrayBuffer()
          const chunks: Blob[] = []

          fileChunks.forEach((chunk, index) => {
               // console.log(chunk.file);

               if (index === 0 || index === fileChunks.length - 1) {
                    // 1. 第一个和最后一个切片的内容全部参与计算
                    chunks.push(chunk.file)
               } else {
                    // 2. 中间剩余的切片我们分别在前面、后面和中间取 文件的 2个字节参与计算
                    // 前面的2字节
                    // chunks.push(chunk.file.slice(0, 2))
                    console.log(chunk.file.slice(0, 2))
                    // 中间的2字节
                    chunks.push(chunk.file.slice(CHUNK_SIZE / 2, CHUNK_SIZE / 2 + 2))
                    // 后面的2字节
                    chunks.push(chunk.file.slice(CHUNK_SIZE - 2, CHUNK_SIZE))
               }
          })

          const fileReader = new FileReader()
          // 读取为 ArrayBuffer 类型的数据，以便进行 MD5 哈希计算。
          fileReader.readAsArrayBuffer(new Blob(chunks))
          fileReader.onload = (e: Event) => {
               spark.append((e.target as FileReader).result)
               resolve(spark.end())
          }
     })
}

// 4.文件上传
const uploadChunks = async (fileChunks: Array<{ file: Blob }>) => {
     // 收集文件切片数据
     const fileData = fileChunks.map((item, index) => {
          return {
               fileHash: fileHash.value, //文件哈希值
               chunkHash: `${fileHash.value}-${index}`, //文件分片哈希值
               itemChunks: item.file, // 文件分片
               size: item.file.size,
               index
          }
     })
     console.log(fileData, '2555556565')

     // 将每一个分片文件转换为 FormData 对象
     const formDatas = fileData.map(({ itemChunks, chunkHash }) => {
          const formData = new FormData()
          // 切片文件
          formData.append('chunk', itemChunks)
          // 切片文件hash
          formData.append('chunkHash', chunkHash)
          // 大文件的文件名
          formData.append('fileName', fileName.value)
          // 大文件hash
          formData.append('fileHash', fileHash.value)
          return formData
     })

     let index = 0
     const max = 6 // 并发请求数量（chrome 默认并发数）
     const taskPool: any = [] // 请求队列
     console.log(taskPool.findIndex((item: any) => item === 565))

     taskPool.splice(taskPool.findIndex((item: any) => item === 565))

     console.log(taskPool)
     while (index < formDatas.length) {
          const task = fetch('http://127.0.0.1:3001/upload', {
               method: 'POST',
               body: formDatas[index]
          })
//           const task = axios.post('http://127.0.0.1:3001/upload',{body: formDatas[index]},{ headers: {
//     'Content-Type': 'multipart/form-data',
//   },})
          // const task = fetch(`http://127.0.0.1:3001/add?id${index}`, { method: 'GET'})

          task.then(() => {
               // debugger
               taskPool.splice(taskPool.findIndex((item: any) => item === task))
          })
          taskPool.push(task)
          if (taskPool.length === max) {
               // debugger
               // 当请求队列中的请求数达到最大并行请求数的时候，得等之前的请求完成再循环下一个
               await Promise.race(taskPool)
          }
          index++
     }
     console.log(taskPool, 'fsdfasfsdf')

     await Promise.all(taskPool)
}

// 1.获取上传的文件
const handleUpload = async (e: Event) => {
     const files = (e.target as HTMLInputElement).files
     if (!files) {
          return
     }
     console.log(files[0])
     fileName.value = files[0].name
     // 调用分片
     const fileChunks = createFileChunks(files[0])
     console.log(fileChunks)
     // 得到 计算的 文件 hash 数据
     const filesHash = await calculateHash(fileChunks)
     console.log(filesHash)
     fileHash.value = filesHash as string
     // 上传文件分片
     await uploadChunks(fileChunks)
}
</script>

<template>
     <input class="upload-demo" type="file" @change="handleUpload" />
</template>

<style scoped>
.upload-demo {
     margin: 50px;
}
</style>
